package model

import (
	"errors"
	"lab-service/config"
	"lab-service/helper"
	ps "lab-service/proto/security"
	"time"
)

type Token struct {
	Id       int64
	Uid      int64
	UpdateAt time.Time `xorm:"updated"`
	ExpireAt time.Time
	RandKey  string
	Role     string
}

func (t *Token) OneById() error {
	ok, err := orm.ID(t.Id).Get(t)
	if !ok {
		return errors.New(TokenNotFound)
	}
	return err
}

func (t *Token) OneByUid() error {
	ok, err := orm.Where("uid = ?", t.Uid).Get(t)
	if !ok {
		return errors.New(TokenNotFound)
	}
	return err
}

func (t *Token) ResetToken() error {
	secCfg := config.GetConfig().SecurityService.Security

	t.ExpireAt = time.Now().Add(secCfg.RandKeyExpiry)
	t.RandKey = helper.RandString(secCfg.RandKeyLen)

	ok, err := orm.ID(t.Id).Cols("rand_key", "expire_at").Update(t)
	if ok == 0 {
		return errors.New(TokenUpdateFailed)
	}
	return err
}

func (t *Token) ExpireToken() error {
	secCfg := config.GetConfig().SecurityService.Security

	if !secCfg.RandKeyEnable {
		return nil
	}

	t.ExpireAt = time.Now()

	ok, err := orm.ID(t.Id).Cols("expire_at").Update(t)
	if ok == 0 {
		return errors.New(TokenUpdateFailed)
	}
	return err
}

func (t *Token) Create() error {
	secCfg := config.GetConfig().SecurityService.Security

	t.ExpireAt = time.Now().Add(secCfg.RandKeyExpiry)
	t.RandKey = helper.RandString(secCfg.RandKeyLen)
	t.Role = ps.Role_Visitor.String()

	ok, err := orm.Insert(t)
	if ok == 0 {
		return errors.New(TokenCreateFailed)
	}
	return err
}

func (t *Token) CheckRdk(token string) error {
	secCfg := config.GetConfig().SecurityService.Security

	if !secCfg.RandKeyEnable {
		return nil
	}

	if t.RandKey != token {
		return errors.New(TokenError)
	}

	if time.Now().After(t.ExpireAt) {
		return errors.New(TokenExpired)
	}

	return nil
}
